/*
 * 文 件 名:  DateTimeUtils.java
 * 版    权:  Huawei Technologies Co., Ltd. Copyright YYYY-YYYY,  All rights reserved
 * 描    述:  VIRest 日期时间通用工具类
 * 修 改 人:  025415/hpli
 * 修改时间:  2011-12-1
 * 跟踪单号:  <跟踪单号>
 * 修改单号:  <修改单号>
 * 修改内容:  <修改内容>
 */
package com.huawei.virest.common.util;

import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.regex.Pattern;

import org.apache.commons.lang.time.FastDateFormat;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.JSONException;

/**
 * VIRest 日期时间通用工具类
 * 
 * @author  025415/hpli
 * @version  [版本号, 2011-12-1]
 * @see  [相关类/方法]
 * @since  [产品/模块版本]
 */
public abstract class DateTimeUtils
{
	private static Log logger = LogFactory.getLog(Utils.class);
	
    private static final FastDateFormat DEFAULT_DATETIME_FORMAT = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss");
    
    /**
     * 时间格式转换
     * @param date String
     * @return Date
     * @throws JSONException [参数说明]
     * @see [类、类#方法、类#成员]
     */
    public static Date parseRFC3339Date(String date) throws JSONException
    {
        Date d = new Date();
        
        try
        {
            //if there is no time zone, we don't need to do any special parsing.
            if (date.endsWith("Z"))
            {
                try
                {
                    SimpleDateFormat s = new SimpleDateFormat(
                            "yyyy-MM-dd'T'HH:mm:ss'Z'");//spec for RFC3339                    
                    d = s.parse(date);
                }
                catch (java.text.ParseException pe)
                {
                    //try again with optional decimals
                    SimpleDateFormat s = new SimpleDateFormat(
                            "yyyy-MM-dd'T'HH:mm:ss.SSSSSS'Z'");//spec for RFC3339 (with fractional seconds)
                    s.setLenient(true);
                    d = s.parse(date);
                }
                return new Timestamp(d.getTime());
            }
            else if (date.lastIndexOf(':') > 19)
            {
                //step one, split off the timezone. 
                String split = "-";
                if (date.lastIndexOf('+') > 10)
                {
                    split = "+";
                }
                String firstpart = date.substring(0, date.lastIndexOf(split));
                String secondpart = date.substring(date.lastIndexOf(split));
                
                //step two, remove the colon from the timezone offset
                secondpart = secondpart.substring(0, secondpart.indexOf(':'))
                        + secondpart.substring(secondpart.indexOf(':') + 1);
                date = firstpart + secondpart;
            }
            else
            {
                SimpleDateFormat s = new SimpleDateFormat(
                        "yyyy-MM-dd'T'HH:mm:ssZ");//spec for RFC3339      
                try
                {
                    d = s.parse(date);
                }
                catch (java.text.ParseException pe)
                {
                    //try again with optional decimals
                    //spec for RFC3339 (with fractional seconds)
                    s = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSSZ");
                    s.setLenient(true);
                    d = s.parse(date);
                }
            }
        }
        catch (ParseException e)
        {
            throw new JSONException("JSON_FORMAT_CONVERSION_FAILED");
        }
        
        return d;
    }
    

    /**
     * 
     * 方法表述
     * @param date date
     * @return Timestamp
     * @throws JSONException 解析异常
     */
    @SuppressWarnings("deprecation")
    public static Timestamp formatDate(String date) throws JSONException
    {
        Timestamp timestamp = null;
        
        if (Utils.isNumber(date))
        {
            timestamp = getTimestamp(Long.parseLong(date));
        }
        else if (isDateFormat(date) || isDatetimeFormat(date))
        {
            timestamp = (Timestamp)parseRFC3339Date(date);
        }
        else if (isSimpleDateFormat(date))
        {
            timestamp = getTimestamp(parseDate(date).getTime());
        }
        else
        {
            timestamp = getTimestamp(Date.parse(date));
        }
        
        return timestamp;
    }
    
    
    /**
     * 
     * 方法表述 取当时日期
     * @param stamp stamp
     * @return String 默认格式: yyyy-MM-dd HH:mm:ss
     */
    public static String getDatetime(Timestamp stamp)
    {
        return DEFAULT_DATETIME_FORMAT.format(stamp);
    }
    
    /**
     * 
     * 方法表述 取当时日期
     * @param date date
     * @return String 默认格式: yyyy-MM-dd HH:mm:ss
     */
    public static String getDatetime(Date date)
    {
        return DEFAULT_DATETIME_FORMAT.format(date);
    }
    
    /**
     * 
     * 方法表述 获取当前时间的timestamp格式
     * @return Timestamp
     */
    public static Timestamp getTimestamp()
    {
        Date now = new Date();
        return new Timestamp(now.getTime());
    }
    
    /**
     * 日期格式检查 如：
     * @param datetime 日期字符串
     * @return boolean true 日期格式正确，false 日期格式不正确
     */
    public static boolean isDatetimeFormat(String datetime)
    {
        String regex = "^(\\d{4})-(0\\d{1}|1[0-2])-(0\\d{1}|[12]\\d{1}|3[01])T"
                + "(0\\d{1}|1\\d{1}|2[0-3]):[0-5]\\d{1}:([0-5]\\d{1})(\\.\\d{0,3}){0,1}"
                + "(Z|[\\+|\\-](0\\d{1}|1\\d{1}|2[0-3]):[0-5]\\d{1})$";
        return Pattern.matches(regex, datetime);
    }
    
    /**
     * RFC 3339日期格式校验
     * @param datetime 日期字符串
     * @return boolean true 日期格式正确，false 日期格式不正确
     */
    public static boolean isDateFormat(String datetime)
    {
        String date = "(\\d{4})-(0\\d{1}|1[0-2])-(0\\d{1}|[12]\\d{1}|3[01])T"
                + "(0\\d{1}|1\\d{1}|2[0-3]):[0-5]\\d{1}:([0-5]\\d{1})(Z|.[0-9]{2}Z|[-|+][0-5]\\d{0,8})";
        return Pattern.matches(date, datetime);
    }
    
    /**
     * 简单日期格式校验
     * @param datetime 日期字符串
     * @return boolean true 日期格式正确，false 日期格式不正确
     */
    public static boolean isSimpleDateFormat(String datetime)
    {
        String date = "(\\d{4})-(0\\d{1}|1[0-2])-(0\\d{1}|[12]\\d{1}|3[01]) "
                + "(0\\d{1}|1\\d{1}|2[0-3]):[0-5]\\d{1}:([0-5]\\d{1})";
        return Pattern.matches(date, datetime);
    }
    
    /**
     * 把RFC 3339格式的时间转换成毫秒值
     * @param date 时间
     * @return Long 结果值
     */
    public static long parseDateToMillionSeconds(String date)
    {
        long millionSeconds = 0;
        
        try
        {
            millionSeconds = formatDate(date).getTime();
        }
        catch (JSONException e)
        {
            logger.error("Datetime Parse Exception! " + e.getCause());
        }
        
        return millionSeconds;
    }
    
    /**
     * 获得系统当前时间
     * @return String [返回类型说明]
     * @see [类、类#方法、类#成员]
     */
    public static String getDatetime()
    {
        return formatDate(new Date());
    }
    
    /**
     * 格式化时间
     * @param obj Object
     * @return String [返回类型说明]
     * @see [类、类#方法、类#成员]
     */
    public static String formatDate(Object obj)
    {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sdf.format(obj);
    }
    
    private static Date parseDate(String source)
    {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        
        try
        {
            return sdf.parse(source);
        }
        catch (ParseException e)
        {
            e.printStackTrace();
        }
        
        return null;
    }
    
    /**
     * 
     * 方法表述 获取当前时间的timestamp格式
     * @param time long
     * @return Timestamp
     */
    public static Timestamp getTimestamp(long time)
    {
        return new Timestamp(time);
    }
}
